﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.ServiceModel.DomainServices.Client;
using ASPItalia.ModelVirtualCasting.Web.RiaServices;
using Microsoft.Windows.Data.DomainServices;

namespace ASPItalia.ModelVirtualCasting.Silverlight.Data
{
    public class DataManager : IDataManager
    {
        private readonly IDictionary<Type, LoadOperation> _pendingLoads = new Dictionary<Type, LoadOperation>();
        private static Lazy<ModelVirtualCastingDomainContext> _domainContext = new Lazy<ModelVirtualCastingDomainContext>(System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);
        public ModelVirtualCastingDomainContext DomainContext { get { return _domainContext.Value; } }
        public EntityContainer EntityContainer
        {
            get { return this.DomainContext.EntityContainer; }
        }

        public DataManager() { }

        public void LoadPeople(QueryBuilder<People> query, Action<ServiceLoadResult<People>> callback, object state)
        {
            this.Load(query.ApplyTo(this.DomainContext.GetPeopleQuery()), lo =>
            {
                callback(this.CreateResult(lo));
            }, state);
        }

        public void LoadMultimediaOfPeople(Action<LoadOperation<Multimedia>> callback, int peopleId)
        {
            EntityQuery<Multimedia> _query = DomainContext.GetMultimediaOfPeopleQuery(peopleId);
            DomainContext.Load(_query, LoadBehavior.RefreshCurrent, callback, null);
        }

        public void UpdatePeople() { DomainContext.SubmitChanges(); }


        #region

        private void Load<T>(EntityQuery<T> query, Action<LoadOperation<T>> callback, object state) where T : Entity
        {
            if (this._pendingLoads.ContainsKey(typeof(T)))
            {
                this._pendingLoads[typeof(T)].Cancel();
                this._pendingLoads.Remove(typeof(T));
            }

            this._pendingLoads[typeof(T)] = this.DomainContext.Load(query, lo =>
            {
                this._pendingLoads.Remove(typeof(T));
                callback(lo);
            }, state);
        }

        private ServiceLoadResult<T> CreateResult<T>(LoadOperation<T> op) where T : Entity
        {
            if (op.HasError)
            {
                op.MarkErrorAsHandled();
            }
            return new ServiceLoadResult<T>(
                new EntityList<T>(this.EntityContainer.GetEntitySet<T>(), op.Entities),
                op.TotalEntityCount,
                op.ValidationErrors,
                op.Error,
                op.IsCanceled,
                op.UserState);
        }

        #endregion
    }
}
